#include "sqlcipher.h"

#include <sqlite3.h>
#include "sql_common.h"

struct __sqlcipher_t {
    sqlite3 *db;
    bool connected;
};

SQLCipher::SQLCipher(QObject *parent) : QObject(parent) {
    sql = new sqlcipher_t;
    sql->connected = false;
}

SQLCipher::~SQLCipher() {
    close();
    delete sql;
}

bool SQLCipher::open(const char *fileName) {
    if(sql->connected) {
        return false;
    }
    int rslt = sqlite3_open(fileName, &(sql->db));
    qDebug() << "db name is " << fileName;
    if(SQLITE_OK == rslt) {
        sql->connected = true;
        return true;
    }
    return false;
}

bool SQLCipher::open(QString fileName) {
    QByteArray ba = fileName.toLatin1(); // must
    const char *dbName = ba.data();
    bool rslt = open(dbName);
    delete dbName;
    return rslt;
}

bool SQLCipher::close() {
    if(sql->connected) {
        sqlite3_close(sql->db);
        sql->connected = false;
        return true;
    }
    return false;
}

bool SQLCipher::isOpen() {
    return sql->connected;
}

bool SQLCipher::setKey(const char *key) {
    if(sql->connected) {
        int rslt = sqlite3_key(sql->db, key, strlen(key));
        if(SQLITE_OK == rslt) {
            return true;
        }
    }
    return false;
}

bool SQLCipher::setKey(QString key) {
    const char *ckey = QString2char(key);
    bool rslt = setKey(ckey);
    delete ckey;
    return rslt;
}


static int callback(void *NotUsed, int argc, char **argv, char **col_name) {
    SQLCipher *that = (SQLCipher *)NotUsed;
    for(int i = 0; i < argc; i++) {
        that->appendData(argv[i] ? argv[i] : "NULL");
    }
}

void SQLCipher::appendData(QString value) {
    data.append(value);
}

bool SQLCipher::exec(const char* cmd) {
    if(sql->connected) {
        char* err_msg = NULL;
        data = "";
        int rslt = sqlite3_exec(sql->db, cmd, callback, (void *)this, &err_msg);
        qDebug() << "exec rslt " << rslt << ", cmd is " << cmd;
        if(SQLITE_OK == rslt) {
            return true;
        } else {
            data = err_msg;
            delete err_msg;
        }
    }
    return false;
}

bool SQLCipher::exec(QString cmd) {
    const char *ccmd = QString2char(cmd);
    const char *tccmd = ccmd;
    bool rslt = exec(tccmd);
    delete ccmd;
    return rslt;
}

QString SQLCipher::getData() {
    return data;
}

